<?php

function __autoload( $className )
{
    $classes_info = __autoload_get_classes_info();

    if ( isset($classes_info[$className]) )
    {
        require $classes_info[$className];

        $methods = get_class_methods($className);
        $static_constructor = "__construct_static";
        if ( in_array($static_constructor, $methods) )
        {
            call_user_func(array($className, $static_constructor));
        }
    }
}

function __autoload_get_classes_dir()
{
    static $classes_dir = null;
    if ( is_null($classes_dir) )
    {
        if ( defined("CLASSES_DIR") )
        {
            $classes_dir = CLASSES_DIR;
        }
        else
        {
            $classes_dir = str_replace('\\', '/', dirname(__FILE__).'/classes/');
        }
    }

    return $classes_dir;
}

function __autoload_get_classes_info()
{
    static $classes_info = null;
    if ( is_null($classes_info) )
    {
        $filename = CACHE_DIR . "autoload_class_info";
        if ( file_exists($filename) )
        {
            $content = file_get_contents( $filename );
            $classes_info = unserialize($content);
        }
        else
        {
            $classes_dir = __autoload_get_classes_dir();
            $classes_info = array();
            __autoload_get_classes_info_impl( $classes_dir, $classes_info );
            file_put_contents( $filename, serialize($classes_info), LOCK_EX );
        }
    }
    return $classes_info;
}

function __autoload_get_classes_info_impl( $path, &$classes_info )
{
    static $phpClassPostfix = ".class.php";
    $regexPattern = sprintf('/%s$/', preg_quote($phpClassPostfix, '/'));

    $dir = dir($path);
    while ( ($entry = $dir->read()) !== false )
    {
        if ( empty($entry) || $entry[0] === '.' || $entry[0] === '~' )
        {
            continue;
        }

        $entryPath = "$path$entry";
        if ( is_file($entryPath) )
        {
            $className = preg_replace($regexPattern, '', $entry);
            if ( $className != $entry )
            {
                $classes_info[$className] = $entryPath;
            }
        }
        else
        {
            __autoload_get_classes_info_impl( "$entryPath/", $classes_info );
        }
    }
    $dir->close();
}

?>
